﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Processing;
using Cloo;
using Processing.Structures;
using General;

namespace KernelTests
{
    class KernelAdder : AKernel
    {
        public long elements;
        public Buffer<Float16> input;
        public Buffer<Float16> output;

        public Float16[] cpuout;

        public override void Dispose()
        {

        }

        protected override bool IsValidInitialized
        {
            get { return true; }
        }

        protected override long[] Dimensions
        {
            get { return new long[] { elements }; }
        }

        protected override string ProgramName
        {
            get { return "Adder"; }
        }

        protected override string ProgramSource
        {
            get
            {
                return @"
                    kernel void Adder(
                        global read_only float16* input,
                        global write_only float16* output
                    )
                    {
                        int i = get_global_id(0);
                        float16 inp = input[i];
                        inp.s0 = inp.s0 + 1;
                        inp.s1 = inp.s1 + 1;
                        inp.s2 = inp.s2 + 1;
                        inp.s3 = inp.s3 + 1;
                        inp.s4 = inp.s4 + 1;
                        inp.s5 = inp.s5 + 1;
                        inp.s6 = inp.s6 + 1;
                        inp.s7 = inp.s7 + 1;
                        inp.s8 = inp.s8 + 1;
                        inp.s9 = inp.s9 + 1;
                        inp.sa = inp.sa + 1;
                        inp.sb = inp.sb + 1;
                        inp.sc = inp.sc + 1;
                        inp.sd = inp.sd + 1;
                        inp.se = inp.se + 1;
                        inp.sf = inp.sf + 1;
                        output[i] = inp;
                    }
                    ";
            }
        }

        protected override void PrepareKernelExecution()
        {
            TimeClock.Start("   GPU Buffer allokkieren");
            output = Processor.AllocateBuffer<Float16>(elements);
            Program.Log("   GPU Buffer allokkieren hat " + TimeClock.GetTime("   GPU Buffer allokkieren") + " Sekunden benötigt.");
        }

        protected override void SetArguments()
        {
            TimeClock.Start("   Argumente setzen");
            SetArgument(0, input);
            SetArgument(1, output, true);
            Program.Log("   Argumente setzen hat " + TimeClock.GetTime("   Argumente setzen") + " Sekunden benötigt.");
        }

        protected override void FinishKernelExecution()
        {
            TimeClock.Start("   Ergebnisdaten zurücklesen");
            cpuout = output.Data;
            Program.Log("   Ergebnisdaten zurücklesen hat " + TimeClock.GetTime("   Ergebnisdaten zurücklesen") + " Sekunden benötigt.");
        }

        public KernelAdder(Processor processor) : base(processor) { }
    }
}
